package ch.ethz.inf.shop.model.simpleDatabase.operators;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import ch.ethz.inf.shop.model.simpleDatabase.Tuple;
import ch.ethz.inf.shop.model.simpleDatabase.TupleSchema;

/**
 * The scan operator reads tuples from a file. The lines in the file contain the
 * values of a tuple. The line a comma separated.
 */
public class Scan extends Operator {

	private static final String DELIMITER = ";";
	private final TupleSchema schema;
	private final BufferedReader reader;

	/**
	 * Contructs a new scan operator.
	 * 
	 * @param fileName
	 *            file to read tuples from
	 */
	public Scan(final String fileName, final String relationName) {

		// create schema

		// read from file
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(fileName));
			String headerLine = reader.readLine();
			if (headerLine == null) {
				throw new Exception("data corrupt, exptected header line in " + fileName);
			}

			StringTokenizer st = new StringTokenizer(headerLine, ";");
			ArrayList<String> colNamesList = new ArrayList<String>();
			while (st.hasMoreTokens()) {
				colNamesList.add(relationName == null || "".equals(relationName) ? st.nextToken() : relationName + "." + st.nextToken());
			}
			this.schema = new TupleSchema(colNamesList);
		} catch (final Exception e) {
			throw new RuntimeException("could not find file " + fileName);
		}
		this.reader = reader;
	}

	@Override
	public boolean moveNext() {

		try {
			// a) read next line

			String line = reader.readLine();
			// b) check if we are at the end of the file (line would be null or
			// empty string if the file was not saved correctly)
			if (line == null || "".equals(line)) {
				// b1. if we reached end of the file, close the buffered reader
				reader.close();
				return false;
			}
			// c) split up comma separated values
			StringTokenizer st = new StringTokenizer(line, DELIMITER);
			ArrayList<String> values = new ArrayList<String>();
			while (st.hasMoreTokens()) {
				values.add(st.nextToken());
			}

			// d) create new tuple using schema and values
			current = new Tuple(this.schema, values.toArray(new String[values.size()]));
			return true;

		} catch (final IOException e) {
			throw new RuntimeException("could not read: " + this.reader + ". Error is " + e);
		}
	}
}
